package com.caishi.lkx.user.api;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;

import com.caishi.lkx.common.BaseApi;
import com.caishi.lkx.common.role.Roles;
import com.caishi.lkx.user.dto.RangeVo;
import com.caishi.lkx.user.dto.UserLogQueryDto;

import com.caishi.lkx.user.ienum.type.HotSearchType;
import com.caishi.lkx.user.ienum.type.UserLogSourceType;
import com.caishi.lkx.user.model.GroupModel;
import com.caishi.lkx.user.service.IGroupService;
import com.caishi.lkx.user.service.ISysDictDetailService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Tag(name = "用户日志相关接口")
@RestController
@RequestMapping("/user/log")
@Slf4j
public class UserLogApi extends BaseApi {

    @Resource
    private IGroupService groupService;

    @Resource
    private ISysDictDetailService dictDetailService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    private static final String REDIS_HOT_KEY = "hotSearch:";

    @PostMapping("/add-hot")
    @Operation(summary = "搜索热词/考试")
    @Parameters({
            @Parameter(name = "type", description = "热词类型"),
            @Parameter(name = "key", description = "热词"),
            @Parameter(name = "expireDays", description = "保留天数"),
    })
    @Roles
    public void addHot(@RequestParam(defaultValue = "word") HotSearchType type, @RequestParam String key, @RequestParam(defaultValue = "8") Integer expireDays) {
        String day = LocalDateTimeUtil.format(LocalDate.now(), "yyyy-MM-dd");
        redisTemplate.opsForZSet().incrementScore(REDIS_HOT_KEY + day + ":" + type.getCode(), key, 1);
        //8天后过期
        redisTemplate.expire(REDIS_HOT_KEY + day + ":" + type.getCode(), expireDays * 24, TimeUnit.HOURS);

    }

    @GetMapping("/get-hot")
    @Operation(summary = "搜索热词/考试")
    @Parameters({
            @Parameter(name = "type", description = "热词类型"),
    })
    @Roles
    public List<RangeVo> getHot(@RequestParam(defaultValue = "word") HotSearchType type, @RequestParam(defaultValue = "10") Long size, @RequestParam(defaultValue = "3") Integer days) {
        LocalDate now = LocalDate.now();
        List<RangeVo> list = new ArrayList<>();
        for (int i = 0; i < days; i++) {
            String day = LocalDateTimeUtil.format(now.plusDays(-1 * i), "yyyy-MM-dd");
            Set<ZSetOperations.TypedTuple<Object>> typedTuples = redisTemplate.opsForZSet().reverseRangeWithScores(REDIS_HOT_KEY + day + ":" + type.getCode(), 0, size);
            if (CollUtil.isNotEmpty(typedTuples)) {
                assert typedTuples != null;
                typedTuples.forEach(r -> {
                    RangeVo build = RangeVo.builder().key((String) r.getValue()).score(r.getScore()).build();
                    list.add(build);
                });
            }
        }
        Map<String, Double> collect = list.stream().collect(Collectors.groupingBy(RangeVo::getKey, Collectors.summingDouble(RangeVo::getScore)));
        List<RangeVo> sortList = new ArrayList<>();
        collect.keySet().forEach(key -> {
            RangeVo build = RangeVo.builder().key(key).score(collect.get(key)).build();
            sortList.add(build);
        });
        return sortList.stream().sorted(Comparator.comparing(RangeVo::getScore).reversed()).limit(size).collect(Collectors.toList());

    }

    @PostMapping("/remove-hot")
    @Operation(summary = "移除热词/考试")
    public void removeHot() {
        String day = LocalDateTimeUtil.format(LocalDate.now().plusDays(-3), "yyyy-MM-dd");
        //热词只保留3天
        redisTemplate.delete(REDIS_HOT_KEY + day + ":" + HotSearchType.word.getCode());
        String examDay = LocalDateTimeUtil.format(LocalDate.now().plusDays(-7), "yyyy-MM-dd");
        //热门考试只保留7天
        redisTemplate.delete(REDIS_HOT_KEY + examDay + ":" + HotSearchType.zhiyeExam.getCode());
        redisTemplate.delete(REDIS_HOT_KEY + examDay + ":" + HotSearchType.gjtkExam.getCode());

    }

    @PostMapping("/group-log")
    @Operation(summary = "机构用户统计")
    public GroupModel groupList(@RequestBody UserLogQueryDto dto) {
        Long groupId = userContext.currentGroupId();
        GroupModel groupModel = groupService.getById(groupId);
        if (null == dto.getSourceTypes() || dto.getSourceTypes().isEmpty()) {
            dto.setSourceTypes(Arrays.asList(UserLogSourceType.values()));
        }

        dto.setGroupId(groupId);
        return groupModel;
    }

}
